/**
 * ------------------------------------------------------------------
 * Copyright reserved by Emin Technology
 * ---- --------------------------------------------------------------
 * <p>
 * PROJECT:		Base
 * FILE:			BaseServiceImpl.java
 * AUTHOR:		sunny
 * DATE CREATION:2011-12-05
 * DESCRIPTION:	base service
 * <p>
 * ==========================================================
 * VERSION CONTROL
 * Number – Date – Author – SVN – Description
 * 01 –  2011-12-05 – sunny – xxx – base service
 * -------------------------------------------------------------------------------------------------------
 */
package top.jle.jpa.basic.service;


import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.transaction.annotation.Transactional;
import top.jle.jpa.basic.dao.*;
import top.jle.jpa.basic.entities.Entity;
import top.jle.jpa.basic.exception.BasicCustomException;
import top.jle.jpa.basic.exception.BasicExceptionCode;
import top.jle.jpa.basic.util.ReflectionUtils;

import java.util.List;
import java.util.Optional;
import java.util.Set;


/**
 * base service
 * @author jim.lee
 *
 */
public abstract class CRUDServiceImpl<T extends Entity> implements CRUDService<T> {

    /** 日志 */
    private static final Logger LOGGER = LoggerFactory.getLogger(CRUDServiceImpl.class);

    @Getter
    private EntityDao entityDao;


    @Autowired
    @Qualifier("entityDao")
    public void setEntityDao(EntityDao entityDao) {
        this.entityDao = entityDao;
    }

    protected Class<T> clazz;

    @Override
    public void setClazz(Class<T> clazz) {

        this.clazz = clazz;
    }

    @SuppressWarnings("unchecked")
    public CRUDServiceImpl() {
        this.clazz = (Class<T>) ReflectionUtils.getSuperClassGenricType(this.getClass(), 0);
    }

    public CRUDServiceImpl(Class<T> clazz) {
        this.clazz = clazz;
    }

    @Override
    public Class<T> getEntityClass() {
        return this.clazz;
    }

    @Override
    public T getReferenceById(long id) {
        return this.entityDao.getReferenceById(this.clazz, id);
    }

    @Override
    public Set<T> getReferencesByIds(Long[] ids) {
        return this.entityDao.getReferencesByIds(this.clazz, ids);
    }

    @Override
    public T findById(Long id) {
        return this.entityDao.findById(this.clazz, id);
    }

    @Override
    public List<T> findAll(SortKey... sortKeys) {
        return this.entityDao.findAll(this.clazz, sortKeys);
    }

    @Override
    public List<T> findByPreFilter(PreFilter... preFilters) {
        return this.entityDao.findByPreFilter(this.clazz, preFilters);

    }

    @Override
    public T findUniqueByPreFilter(PreFilter... preFilter) {
        return this.entityDao.findUniqueByPreFilter(this.clazz, preFilter);
    }

    @Override
    public List<T> findByIds(Long[] ids) {
        return this.entityDao.findByIds(this.clazz, ids);
    }


    @Override
    public PagedResult<T> getPage(PageRequest pageRequest, PreFilter... preFilter) {
        return this.entityDao.getPage(clazz, pageRequest, preFilter);
    }

    @Override
    public int getAllCount() {
        return this.entityDao.getAllCount(this.clazz);
    }

    @Override
    public int getCountByPreFilter(PreFilter... preFilter) {
        return this.entityDao.getCountByPreFilter(this.clazz, preFilter);
    }
    @Override
    public int getCountByPreFilters(PreFilter... preFilter) {
        return this.entityDao.getCountByPrefilters(this.clazz, preFilter);
    }

    @Override
    public boolean existsByPreFilter(PreFilter... preFilter) {
        return this.entityDao.existsByPreFilters(this.clazz, preFilter);
    }

    @Override
    public void update(T entity) {
        this.entityDao.update(entity);
    }

    @Override
    @Transactional
    public void delete(T entity) {
        LOGGER.debug("Delete the entity");
        this.entityDao.delete(entity);

    }

    @Override
    @Transactional
    public void deleteById( Long id) {
        T entity = this.findById(Optional.ofNullable(id).orElseThrow(()->new BasicCustomException(BasicExceptionCode.INVALID_PARAM)));
        if (entity != null) {
            this.delete(entity);
        }
    }

    @Override
    public void deleteByIds(Long[] ids) {
        List<T> entities = this.findByIds(ids);
        for (T entity : entities) {
            this.delete(entity);
        }
    }

    @Override
    public void save(T entity) {
        this.entityDao.save(entity);
    }

    @Override
    @Transactional
    public void saveOrUpdate(T entity) {
        this.entityDao.saveOrUpdate(entity);
    }



    public void flush() {
        this.entityDao.flush();
    }

    @Override
    public List<T> findByPreFilter(SortKey[] sortKeys, PreFilter... preFilters) {
        return this.entityDao.findByPreFilter(this.clazz, sortKeys, preFilters);
    }



}